package com.qk.management.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSErrorCode;
import com.aliyun.oss.OSSException;
import com.qk.common.constants.AvatarMessageConstants;
import com.qk.common.enums.AvatarErrorCode;
import com.qk.common.storage.FileStorageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.io.InputStream;
import java.util.UUID;

@Service
@Slf4j
public class AliyunOSSStorageStrategy implements FileStorageStrategy {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    @Value("${aliyun.oss.accessKeyId:}")
    private String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret:}")
    private String accessKeySecret;

    private OSS ossClient;

    @PostConstruct
    public void init() {
        if (accessKeyId != null && !accessKeyId.isEmpty() && 
            accessKeySecret != null && !accessKeySecret.isEmpty()) {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        } else {
            log.warn(AvatarErrorCode.OSS_CREDENTIALS_NOT_CONFIGURED.getMessage());
        }
    }

    @PreDestroy
    public void destroy() {
        if (ossClient != null) {
            ossClient.shutdown();
        }
    }

    @Override
    public String storeFile(MultipartFile file) throws Exception {
        if (ossClient == null) {
            throw new RuntimeException(AvatarErrorCode.OSS_CLIENT_NOT_INITIALIZED.getMessage());
        }

        String fileName = generateUniqueFileName(file.getOriginalFilename());
        
        try (InputStream inputStream = file.getInputStream()) {
            ossClient.putObject(bucketName, fileName, inputStream);
            return AvatarMessageConstants.OSS_URL_FORMAT.replace("{}", bucketName).replace("{}", endpoint) + "/" + fileName;
        } catch (OSSException oe) {
            log.error("{} {}, {}: {}, {}: {}", 
                     AvatarMessageConstants.OSS_ERROR, AvatarMessageConstants.OSS_ERROR_CODE, oe.getErrorCode(), AvatarMessageConstants.OSS_ERROR_MESSAGE, oe.getMessage(), AvatarMessageConstants.OSS_ERROR_REQUEST_ID, oe.getRequestId());
            throw new RuntimeException(AvatarErrorCode.FILE_UPLOAD_FAILED.getMessage() + ": " + oe.getMessage());
        }
    }

    @Override
    public void deleteFile(String fileUrl) throws Exception {
        if (ossClient == null) {
            throw new RuntimeException(AvatarErrorCode.OSS_CLIENT_NOT_INITIALIZED.getMessage());
        }

        String fileName = extractFileNameFromUrl(fileUrl);
        
        if (doesFileExist(fileName)) {
            ossClient.deleteObject(bucketName, fileName);
            log.info("{}: {}", AvatarMessageConstants.SUCCESSFULLY_DELETED_FILE, fileName);
        } else {
            log.warn("{}: {}", AvatarMessageConstants.OSS_FILE_NOT_FOUND, fileName);
        }
    }

    @Override
    public boolean doesFileExist(String fileUrl) {
        if (ossClient == null) {
            throw new RuntimeException(AvatarErrorCode.OSS_CLIENT_NOT_INITIALIZED.getMessage());
        }

        try {
            String fileName = extractFileNameFromUrl(fileUrl);
            return ossClient.doesObjectExist(bucketName, fileName);
        } catch (OSSException oe) {
            if (OSSErrorCode.NO_SUCH_KEY.equals(oe.getErrorCode())) {
                return false;
            }
            throw new RuntimeException(AvatarErrorCode.FILE_DELETE_FAILED.getMessage() + ": " + oe.getMessage());
        }
    }

    private String generateUniqueFileName(String originalFileName) {
        String extension = "";
        if (originalFileName != null && originalFileName.contains(".")) {
            extension = originalFileName.substring(originalFileName.lastIndexOf("."));
        }
        return AvatarMessageConstants.OSS_AVATAR_PATH + UUID.randomUUID().toString().replace("-", "") + extension;
    }

    private String extractFileNameFromUrl(String fileUrl) {
        return fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
    }
}